#include "socket_tool.h"
#include <unistd.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>


ssize_t readn(int sockfd, char *buf, size_t n)
{
    // 剩余需要读取的字节数
    size_t nleft = n;
    ssize_t read_count;
    while (nleft > 0) {
        read_count = read(sockfd, buf, nleft);
        if (read_count < 0) { // 发生错误
            if (errno == EINTR) { 
                // 系统中断，重试
                read_count = 0;
            } else
                return -1;
        } else if (read_count == 0) {
            // 对于文件，读取数为0表示读到文件末尾了；
            // 对于tcp socket，读取数为0表示对端已关闭连接
            break;
        }

        nleft -= read_count;
        buf += read_count;
    }
    // 返回读取的字符数
    return (n - nleft);
}


ssize_t recvn(int sockfd, char *buf, size_t n, int flags)
{
    size_t nleft = n;
    ssize_t recv_count;
    while (n > 0)
    {
        recv_count = recv(sockfd, buf, nleft, flags);
        if (recv_count < 0) {
            if (errno == EINTR)
                recv_count = 0;
            else
                return -1;
        } else if (recv_count == 0)
            break;
        nleft -= recv_count;
        buf += recv_count;
    }
    return (n - nleft);
}

String* read_tcp_line(int sockfd)
{
    String_Ptr str = Init_String(READ_BYTES);

    size_t buf_len = READ_BYTES;
    char buf[buf_len];
    memset(buf, 0, sizeof(buf));

    while (true) {
        ssize_t read_count;
        if ((read_count = recv(sockfd, buf, buf_len, MSG_PEEK)) == -1) // 未读取到数据，返回空
            return str;
        else if (read_count == 0) { // 连接被关闭
            Destroy_String(str);
            return NULL;
        }

        ssize_t index = terminator_at(buf, read_count);
        if (index == -1) {
            // 没有换行符，先正式读走数据，然后继续读
            read_count = recv(sockfd, buf, buf_len, 0);
            Append_Chars(str, buf, read_count);
        } else {
            // 读取换行符前的字节
            read_count = readn(sockfd, buf, index + 1);
            // 不需要换行符
            Append_Chars(str, buf, read_count - 1);
            return str;
        }
    }

    return str;
}

/** 
  * 寻找buf中第一个换行符的位置
  * date:2025-08-29 15:18 
  */
ssize_t terminator_at(const char *buf, size_t len) {
    if (buf == NULL)
        return -1;
    for (size_t i = 0; i < len; ++i)
        if (buf[i] == '\n')
            return i;
    return -1;
}

char *sockaddr_to_string(const struct sockaddr_in *ipv4)
{
    size_t str_len = INET_ADDRSTRLEN + 6;
    char *str = (char*) calloc(str_len + 1, sizeof(char));
    char ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, ipv4, ip, sizeof(ip));
    snprintf(str, str_len + 1, "%s:%d", ip, ntohs(ipv4->sin_port));
    return str;
}
